#ifndef _OH_STORAGE_H
#define _OH_STORAGE_H

#include <oh/base.h>

_OH_BEGIN

// not finished yet
template<typename A_Target>
class Storage
{
public:
    typedef A_Target	stored;
	typedef stored *	pointer;
	typedef stored &	reference;
    typedef stored const *	const_pointer;
    typedef stored const &	const_reference;

private:
	class _Base{
	public:
		virtual _Base * clone ( ) = 0;
		virtual stored & getSome( ) = 0;
		virtual stored const & getSome( ) const = 0;
		virtual ~_Base ( ) = 0
		{}
	};
	template<class ActualType>
	class _Actual
		:public _Base
	{
	public:
		_Actual( )
			:_ptr(NULL)
		{}
		_Actual(_Actual const& a_right)
			:_ptr(!(a_right._ptr) ? NULL : new ActualType(*(a_right._ptr)))
		{}
		explicit _Actual(ActualType const& a_right)
			:_ptr(new ActualType(a_right))
		{
		}
		explicit _Actual(ActualType const*const a_pRight)
			:_ptr(a_pRight)
		{}
		~_Actual( )
		{
			delete _ptr;
		}
		_Actual & operator= (_Actual const& a_right)
		{
			if(*this == a_right)
				return *this;

			_ptr = (!(a_right._ptr) ? NULL : new ActualType(*(a_right._ptr)));

			return *this;
		}
		Bool const operator== (_Actual const& a_right)
		{
			return (_ptr == a_right._ptr);
		}
		Bool const operator!= (_Actual const& a_right)
		{
			return !(*this == a_right);
		}

		_Actual * clone( )
		{
			return new _Actual<ActualType>(*this);
		}
		ActualType & getSome( )
		{
			return *_ptr;
		}
		ActualType const & getSome( ) const
		{
			return *_ptr;
		}

	private:
		ActualType * _ptr;
	};

public:
	Storage( )
		:_ptr(NULL)
	{}
	Storage(Storage const & a_right)
		:_ptr(!_ptr ? NULL : a_right._ptr->clone())
	{}

	template<class ActualType>
	explicit Storage(ActualType const& a_item, typename SelectTypeIf<CONVERTS(ActualType,stored),bool,void>::Result const a_compatible = true)
		:_ptr(new _Actual<ActualType>(a_item))
	{}
	template<class ActualType>
	explicit Storage(ActualType const*const a_pItem, typename SelectTypeIf<CONVERTS(ActualType,stored),bool,void>::Result const a_compatible = true)
		:_ptr(new _Actual<ActualType>(a_pItem))
	{}
    ~Storage( )
    {
		delete _ptr;
	}

	Storage & operator= (Storage const &a_right)
	{
		if(*this == a_right)
			return *this;

		delete _ptr;
		_ptr = (!a_right._ptr ? NULL : a_right._ptr->clone());

		return *this;
	}
	Bool const operator== (Storage const &a_right)
	{
		return (_ptr == a_right.ptr);
	}
	Bool const operator!= (Storage const &a_right)
	{
		return !(*this == a_right);
	}

public:
	reference gain( )
	{
		return _ptr->getSome();
	}
    const_reference peek() const
    {
        return _ptr->getSome();
    }

	template<class ActualType>
    void store(ActualType const& a_item, typename SelectTypeIf<CONVERTS(ActualType, stored),bool,void>::Result const a_compatible = true)
    {
		delete _ptr;
        _ptr = new _Actual<ActualType>(a_item);
    }
	template<class ActualType>
	void capture(ActualType const*const a_pItem, typename SelectTypeIf<CONVERTS(ActualType, stored),bool,void>::Result const a_compatible = true)
	{
		delete _ptr;
		_ptr = new _Actual<ActualType>(a_pItem);
	}

protected:
    _Base * _ptr;
};

_OH_END

#endif // _OH_STORAGE_H